#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <fstream> 
#include <sstream> 
#include "online-certifier/communicator/dataProxyCommunicator.hh"
#include "online-certifier/util/typeDefines.hh"
#include "online-certifier/util/generatePrime.inl"

using namespace std;


int getdir (char* dir, vector<string> &files)
{
    DIR *dp;
    struct dirent *dirp;
    if((dp  = opendir(dir)) == NULL) {
        cout << "Error(" << errno << ") opening " << dir << endl;
        return errno;
    }

    while ((dirp = readdir(dp)) != NULL) {
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    return 0;
}


int delDir(char* dirName)
{
    cout << "[data-proxy] deleting directory: " << dirName << endl;
    if (rmdir(dirName))
        return 1;
    else
    {
        perror("[data-proxy]");
        return 0;
    }
}

void delAllFiles(char* dir, vector<string>& files){

    files.clear();//coult use a better way to enhance performance
    getdir(dir,files);
    string fullName;

    for(int i =0; i < files.size(); i++){

        if(files[i] != "." && files[i] != ".."){
            fullName = dir + files[i];
            cout << "[data-proxy] deleting: " << fullName << endl;
            if( remove(fullName.c_str()) != 0){ //delete the file
                cerr << "[data-proxy] error: cannot delete  " << fullName << endl;
                perror(fullName.c_str());
            }

        }
    }
}

int main(int argc, char** argv)
{
    vector<string> sites;
    char* dir;
    int port;
    dataProxyCommunicator* comm; 

    if(argc == 1){
        //read args from comfig file. if fails
        ifstream conf("dataProxy.conf");

        if(!conf.is_open()){
            perror("Can't read dataProxy.conf");
            exit(1);
        }
        string line;
        int i;
        for(i=0; !conf.eof();){
            getline(conf, line);
            if(!(line.empty() || line[0] == '#' )){

                if(i==0){
                    port = atoi(line.c_str());
                }else if(i == 1){
                    dir = new char[line.size()];
                    strcpy(dir, line.c_str());
                }
                i++;
            }
            
            comm = new dataProxyCommunicator(port);  
        }
        if(i < 2){
            cerr << "[data-proxy] wrong config file!" << endl;
            conf.close();
            exit(1);

        }

        conf.close();
    }else if(argc == 3){

        port = atoi(argv[1]);
        dir = argv[2];
        comm = new dataProxyCommunicator(port);  
    }else{

        cerr << "Few Arguments! (no config file)" << endl;
        cerr << "Usage: dataProxy port dir_name" << endl;
    
        exit(1);

    }

    vector<string> files;
	ifstream f;
	string line;
	size_t i;
	string fullName;


    // creating a new task
    cout << "[data-proxy] creating task directory: " << dir << endl;
    if(mkdir(dir,0700)==-1)//creating a directory
    {
        cerr<<"[data-proxy] Error :  "<<strerror(errno)<<endl;

        cout << "[data-proxy] checking if there are files in output dir.." << endl;
        delAllFiles(dir, files);
    }

    if(comm->runDataProxyServer() == ERROR) // starting the server
        return ERROR;

    while(1)
    {
        files.clear();

	    getdir(dir,files);
	
	
	    for (i = 0;i < files.size() ; i++) {
	
	        if(files[i] != "." && files[i] != "..")
	        { 
	            fullName = dir + files[i];
	            cout << "[data-proxy] reading: " << files[i] << endl;
                f.open(fullName.c_str(), ios::in);
	           
                if (f.is_open())
                {
                    while (!f.eof() )
                    {
                        getline (f,line);
                        if(line[0] == '$') // means the file is locked
                        {
                            cout << "[data-proxy] file is locked!!" << endl;
                            break;
                        }else{//means the lock is removed and we have data :) (or the file is empty)
                            if(!line.empty()){

                                comm->writeRowDataToDecoder(line);
                                f.close();

                                cout << "[data-proxy] deleting: " << files[i] << endl;
                                if( remove(fullName.c_str()) != 0){ //delete the file
                                    cerr << "[data-proxy] error: cannot delete  " << files[i] << endl;
                                    perror(fullName.c_str());
                                }
                            }
                        }
                    }
                    f.close();

                }
                else cerr << "[data-proxy] unable to open " << files[i] << endl; 
            }
        }//end reading all files

        e_status chk = comm->checkTerminate();
        if(chk == SUCCESS || chk==  DISCONNECTED){
      
            cout << "[data-proxy] checking if there are files in output dir: " << dir <<  endl;

            delAllFiles(dir, files);

            delDir(dir);
            delete comm;
            delete dir;
            return 0;
        }

    }
    
}
